#include "pcapsender.h"
#include "packetcapapi.h"
#include <QDebug>

CPCapSender::CPCapSender(QObject *parent) :
    QObject(parent)
{
    qDebug("[CPCapSender]constructed");
}

CPCapSender::~CPCapSender()
{
    qDebug("[CPCapSender]destroyed");
}

bool CPCapSender::sendPacket(CPCapPacket *packet)
{
    if (!m_pcap) {
        return false;
    }

    QByteArray data;
    if (!packet->buildPacket(data)) {
        return false;
    }

    pcap_t *pcap_handle = reinterpret_cast<pcap_t*>(m_pcap);
    if (!pcap_handle) {
        qCritical() << "Sender: pcap handle is null";
        return false;
    }

    int result = wpcap_api_arg3(pcap_sendpacket, pcap_handle,
                                (const u_char*)data.data(), data.length());
    if (0 != result) {
        qCritical() << "Sender: send packet failed:\n" << data.toHex();
        return false;
    } else {
        qDebug() << "Sender: send packet:\n" << data.toHex();
    }
    return true;
}

CPCapHandle *CPCapSender::handle() const
{
    return m_handle;
}

void CPCapSender::setHandle(CPCapHandle *handle)
{
    m_handle = handle;
    emit handleChanged();
}

bool CPCapSender::open(CPCapDev *dev)
{
    close();

    int snaplen = 65536;
    int flags = PCAP_OPENFLAG_PROMISCUOUS;
    int timeout = 1000;
    const char *source = dev->source().toStdString().c_str();

    if (m_handle) {
        m_handle->setSource(dev->source());
        snaplen = m_handle->snaplen().toInt();
        timeout = m_handle->timeout().toInt();
    }

    char errbuf[PCAP_ERRBUF_SIZE];
    m_pcap = wpcap_api_arg6(pcap_open, source, snaplen, flags, timeout, NULL, errbuf);
    if (NULL == m_pcap) {
        qCritical() << "Sender: " << errbuf;
        return false;
    }
    return true;
}

void CPCapSender::close()
{
    if (m_pcap) {
        wpcap_api_arg1(pcap_close, (pcap_t *)m_pcap);
        m_pcap = NULL;
    }
}
